/**
 * File InformationAgentCB.java created by Pablo Díaz Fernández
 * on 21/04/2012 for the project supply-chain-simulator
 */
package org.lsk.pfc.scsim.model.behaviour;

import jade.core.behaviours.CyclicBehaviour;
import jade.lang.acl.ACLMessage;

import java.util.List;

import org.apache.log4j.Logger;
import org.lsk.pfc.scsim.model.agent.InformationAgent;
import org.lsk.pfc.scsim.model.messages.InformationAgentMessageFactory;
import org.lsk.pfc.scsim.model.messages.MessageFactory;
import org.lsk.pfc.scsim.model.persistence.dto.NeedDTO;
import org.lsk.pfc.scsim.model.persistence.dto.RequestDTO;
import org.lsk.pfc.scsim.model.persistence.dto.StockDTO;

/**
 * Cyclic behaviour executed for every information agent of the different
 * multi-agent systems of the supply chain.
 * 
 * @author Pablo Díaz Fernández
 */
public final class InformationAgentCB extends CyclicBehaviour {

	/**
	 * Serial version ID.
	 */
	private static final long serialVersionUID = 3331547177105809330L;

	/**
	 * Logger for the class.
	 */
	private static final Logger LOGGER = Logger
	        .getLogger(InformationAgentCB.class);

	/**
	 * Agent that runs the behaviour.
	 */
	private InformationAgent agent = (InformationAgent) this.myAgent;
	/**
	 * Factory for all the messages related to the information agent.
	 */
	private InformationAgentMessageFactory iaMsgFactory = MessageFactory
	        .getInformationAgentMF();

	/**
	 * 
	 * @see jade.core.behaviours.Behaviour#action()
	 */
	@Override
	public void action() {

		ACLMessage inMsg = null;
		do {
			inMsg = this.myAgent.blockingReceive();
		} while (inMsg == null);

		LOGGER.debug("[" + agent.getName() + "] Query received from CA\n"
		        + inMsg);

		long tick = MessageFactory.extractTick(inMsg);
//		if (tick == -1) {
//			throw new TickNotSentException(this.myAgent.getName());
//		}

		ACLMessage outMsg = null;
		if (iaMsgFactory.isGetNeeds(inMsg)) {
			outMsg = processNeedsQuery(inMsg, tick);
			agent.send(outMsg);

		} else if (iaMsgFactory.isGetStocks(inMsg)) {
			outMsg = processStocksQuery(inMsg, tick);
			agent.send(outMsg);

		} else if (iaMsgFactory.isPersistRequests(inMsg)) {
			RequestDTO requestDTO = iaMsgFactory.parseRequestPersistMessage(
					inMsg);
			agent.getRequestDAO().createOrUpdate(requestDTO);
		}
		this.myAgent.send(outMsg);

		LOGGER.debug("[" + agent.getName() + "] Response sent to CA\n" 
				+ outMsg);
	}

	/**
	 * Processes the messages that query the information agent for stocks in the
	 * specified tick time.
	 * 
	 * @param inMsg
	 *            Query message.
	 * @param tick
	 *            Current time tick.
	 * @return Response message with the stocks of the multi agent system in the
	 *         specified tick.
	 */
	private ACLMessage processStocksQuery(final ACLMessage inMsg,
	        final long tick) {
		ACLMessage response;
		Integer value = null;
		StockDTO template = new StockDTO();
		template.setTick(tick);
		template.setSourceName(agent.getMasName());
		List<StockDTO> stocks = agent.getStockDAO().list(template);
		StockDTO stockDTO = stocks.get(0);
		value = stockDTO.getAmount();
		response = iaMsgFactory.responseMessage(value.toString(), inMsg);
		return response;
	}

	/**
	 * Processes the messages that query the information agent for needs in the
	 * specified tick time.
	 * 
	 * @param inMsg
	 *            Query message.
	 * @param tick
	 *            Current time tick.
	 * @return Response message with the needs of the multi agent system in the
	 *         specified tick.
	 */
	private ACLMessage processNeedsQuery(final ACLMessage inMsg,
			final long tick) {
		ACLMessage response;
		Integer value = null;
		NeedDTO template = new NeedDTO();
		template.setTick(tick);
		template.setSourceName(agent.getMasName());
		List<NeedDTO> needs = agent.getNeedDAO().list(template);
		NeedDTO needDTO = needs.get(0);
		if (needDTO != null) {
			value = needDTO.getAmount();
		}
		response = iaMsgFactory.responseMessage(value.toString(), inMsg);
		return response;
	}
}
